package com.qzsoft.zhjd.laboratory.modules.asphaltSofteningPoint.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qzsoft.jeemis.common.exception.RenException;
import com.qzsoft.zhjd.common.components.BaseServiceComponent;
import com.qzsoft.zhjd.common.utils.ZhjdIotUtils;
import com.qzsoft.zhjd.laboratory.modules.asphaltPenetrometer.entity.AsphaltPenetrometerResEntity;
import com.qzsoft.zhjd.laboratory.modules.asphaltSofteningPoint.entity.AsphaltSofteningPointEntity;
import com.qzsoft.zhjd.laboratory.modules.asphaltSofteningPoint.entity.AsphaltSofteningPointResEntity;
import com.qzsoft.zhjd.laboratory.modules.asphaltSofteningPoint.mapper.AsphaltSofteningPointMapper;
import com.qzsoft.zhjd.laboratory.modules.asphaltSofteningPoint.mapper.AsphaltSofteningPointResMapper;
import com.qzsoft.zhjd.laboratory.modules.asphaltSofteningPoint.service.AsphaltSofteningPointResService;
import com.qzsoft.zhjd.laboratory.modules.asphaltSofteningPoint.service.AsphaltSofteningPointService;
import com.qzsoft.zhjd.laboratory.modules.errorRecord.service.ErrorRecordService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Service("asphaltSofteningPointService")
public class AsphaltSofteningPointServiceImpl extends ServiceImpl<AsphaltSofteningPointMapper, AsphaltSofteningPointEntity> implements AsphaltSofteningPointService {

    @Autowired
    private AsphaltSofteningPointMapper asphaltSofteningPointMapper;

    @Autowired
    private AsphaltSofteningPointResMapper resMapper;

    @Autowired
    private AsphaltSofteningPointResService asphaltSofteningPointResService;

    @Autowired
    private BaseServiceComponent baseServiceComponent;

    @Autowired
    private ErrorRecordService errorRecordService;

    private static Map<String, String> currentMap = new HashMap<>();
    private static final String DEVICE_ID = "08271aa6c92d7b6ac5efbc77fff02749";

    /**
     * 列表
     */
    @Override
    public IPage<JSONObject> queryPage(Map<String, Object> params) {
        IPage<AsphaltSofteningPointEntity> page = baseServiceComponent.getPage(params, AsphaltSofteningPointEntity.class);
        return asphaltSofteningPointMapper.queryPage(page, params);
    }

    /**
     * 信息
     *
     * @return AsphaltSofteningPointEntity
     */
    @Override
    public AsphaltSofteningPointEntity getInfo(String id) {
        return getById(id);
    }

    /**
     * 保存
     */
    @Override
    public void saveData(AsphaltSofteningPointEntity asphaltSofteningPoint) {
        save(asphaltSofteningPoint);
    }

    /**
     * 修改
     */
    @Override
    public void updateData(AsphaltSofteningPointEntity asphaltSofteningPoint) {
        updateById(asphaltSofteningPoint);
    }

    /**
     * 删除单条数据
     *
     * @param id
     */
    @Override
    public void deleteOneData(String id) {
        removeById(id);
    }

    /**
     * 删除
     */
    @Override
    public void deleteData(List<String> ids) {
        removeByIds(ids);
    }

    /**
     * 解析济微三标沥青软化点试验仪数据——航天科宇公司设备v2.x
     * 示例：FAFBFC0C02A4004217010156020156AD
     * FAFBFC13
     * A7——结果数据
     * 08——分钟8
     * 2F——秒47
     * 01E9——温度，带一位小数48.9
     * 08——分钟8
     * 31——秒49
     * 01EB——温度，带一位小数49.1
     * 0000000000000000
     * 03——通道1+通道2数据； 00——无效数据；01——通道1数据；02——通道2数据；03——通道1，通道2数据
     * F4——校验和
     * @param resData  试验结果数据
     * @param deviceId 试验设备id
     */
    @Override
    public void parsingData(String resData, String deviceId) {

        try {
            //处理多个“FAFBFC”数据；
            List<String> resDatas = transfer(resData);
            for(String res : resDatas){
                parseLabData(res,deviceId);
            }
        } catch (Exception e) {
            errorRecordService.saveErrorData(ZhjdIotUtils.ASPHALT_SOFTENING_POINT,deviceId,resData);
            throw new RenException("数据解析异常");
        }

    }

    @Override
    public void parsingCJData(byte[] rawData, String deviceId) {
        double[] softeningPoints = this.parseSofteningPoints(rawData);
        if(softeningPoints!=null){
            AsphaltSofteningPointEntity p = new AsphaltSofteningPointEntity();
            p.setTemp1(new BigDecimal(softeningPoints[0]));
            p.setTemp2(new BigDecimal(softeningPoints[1]));
            p.setDeviceId(deviceId);
            this.save(p);
        }
    }

    public  double[] parseSofteningPoints(byte[] rawData) {
        Double sp1 = null; // E
        Double sp2 = null; // F

        int i = 0;
        while (i < rawData.length) {
            byte b = rawData[i];

            // 检查是否是 E 或 F 标识符
            if (b == 'E' || b == 'F') {
                // 确保后面有完整的8字节帧
                if (i + 1 + 8 <= rawData.length) {
                    byte[] frame = new byte[8];
                    System.arraycopy(rawData, i + 1, frame, 0, 8);

                    if (isValidFrame(frame)) {
                        // 提取中间5字节（索引1~5）
                        String numStr = new String(frame, 1, 5).trim();
                        try {
                            double value = Double.parseDouble(numStr);
                            if (b == 'E') {
                                sp1 = value;
                            } else if (b == 'F') {
                                sp2 = value;
                            }
                        } catch (NumberFormatException ignored) {
                            // 忽略非法数值
                        }
                    }

                    // 跳过标识符 + 8字节帧
                    i += 1 + 8;
                    continue;
                }
            }

            i++; // 继续查找
        }

        // 只有当两个软化点都解析成功才返回
        if (sp1 != null && sp2 != null) {
            return new double[]{sp1, sp2};
        } else {
            return null; // 或抛异常，按需处理
        }
    }

    /**
     * 校验是否为合法的8字节数据帧
     */
    private static boolean isValidFrame(byte[] frame) {
        if (frame.length != 8) return false;
        if (frame[0] != 0x20) return false;       // 必须以空格开头
        if (frame[7] != 0x13) return false;       // 必须以 DC3 (19) 结尾

        // 检查中间5字节是否为数字/空格/小数点
        for (int j = 1; j <= 5; j++) {
            char c = (char) frame[j];
            if (!(c == ' ' || c == '.' || (c >= '0' && c <= '9'))) {
                return false;
            }
        }
        return true;
    }


    /**
     * 将请求参数转化为以FAFBFC开头的字符串集合；
     * @param resData
     * @return
     */
    private List<String> transfer(String resData) {
        if(resData == null || !resData.contains("FAFBFC")){
            throw new RenException("软化点数据解析异常：" + resData);
        }
        //如果只有一个FAFBFC...数据，直接返回；
        if(resData.indexOf("FAFBFC") == resData.lastIndexOf("FAFBFC")){
            List<String> resDatas = new ArrayList<>();
            resDatas.add(resData);
            return resDatas;
        }
        //拼接第一个FAFBFC数据，有可能被截断，先查询上一条记录的原始数据，子表或主表
        //todo
        List<String> parts = new ArrayList<>();
        //按FAFBFC开头的字符串截取，获取有效的试验数据List；
        Pattern pattern = Pattern.compile("FAFBFC.*?(?=FAFBFC|$)", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(resData);

        while (matcher.find()) {
            parts.add(matcher.group());
        }
        return parts;
    }

    //四标
    /**
     * FAFBFC0C02A4000314010318020318F3
     *
     * FAFBFC
     * 0C02
     * A4——试验实时数据
     * 00——flag
     * 03——时间，3分
     * 14——时间，20秒
     * 01——编号，01
     * 0318——温度，79.2℃
     * 02——编号，02
     * 0318——温度，79.2℃
     * F3——sum，校验和
     */

    private void parseLabData(String resData, String deviceId) {
        Date nowDate = new Date();
        try {
            List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(resData);
            //如果数据以00开头，可能设备刚开机或重启，表示一次新的实验开始
            if (StringUtils.equals(dataList.get(0), "00")) {
                currentMap.remove(deviceId);
            }
            //验证位不进行校验
            int i = 4;
            //如果是四标的（四标试验仪器是蓝航中科的，解析协议和航天科宇的不一样），i=5;
            if (StrUtil.equals(DEVICE_ID, deviceId)) {
                i = 5;
            }
            //试验数据
            if (StringUtils.equals(ZhjdIotUtils.DATA_TYPE_TEST, dataList.get(i))) {
                AsphaltSofteningPointEntity entity = new AsphaltSofteningPointEntity();
                entity.setDeviceId(deviceId);
                if (currentMap.get(deviceId) == null) {
                    AsphaltSofteningPointResEntity resEntity = new AsphaltSofteningPointResEntity();
                    resEntity.setDeviceId(deviceId);
                    asphaltSofteningPointResService.save(resEntity);
                    currentMap.put(deviceId, resEntity.getId());
                }
                //设置实验结果数据id
                entity.setResId(currentMap.get(deviceId));

                entity.setOriginalData(resData);
                entity.setCreateTime(nowDate);
                i++;
                entity.setFlag(dataList.get(i));

                // 将16进制转换为10进制数据，不含（0x）
                i++;
                entity.setMin(Integer.parseInt(dataList.get(i), 16));  // 分
                i++;
                entity.setSecond(Integer.parseInt(dataList.get(i), 16));  // 秒
                i++; // 温度1
                //四标，蓝航中科时
                if(StrUtil.equals(DEVICE_ID,deviceId)){
                    //num1;
                    entity.setNum1(Integer.parseInt(dataList.get(i),16));
                    //DT1;
                    i++;
                    entity.setTemp1(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+dataList.get(i + 1)));
                    i++;
                    i++;
                    //num2
                    entity.setNum2(Integer.parseInt(dataList.get(i),16));
                    //DT2;
                    i++;
                    entity.setTemp2(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+dataList.get(i + 1)));

                } else {
                    entity.setTemp1(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+dataList.get(i + 1)));
                    i ++;
                    entity.setStirringGear(dataList.get(i));
                    i++;
                    entity.setStatus(dataList.get(i));
                }
                save(entity);
                //结果数据
            } else if (StringUtils.equals(ZhjdIotUtils.DATA_TYPE_RES, dataList.get(i))) {
                AsphaltSofteningPointResEntity resEntity = new AsphaltSofteningPointResEntity();
                resEntity.setId(currentMap.get(deviceId));
                currentMap.remove(deviceId);
                resEntity.setDeviceId(deviceId);
                resEntity.setOriginalData(resData);
                resEntity.setCreateTime(nowDate);

                // 将16进制转换为10进制数据，不含（0x）
                i++;
                resEntity.setMin(Integer.parseInt(dataList.get(i), 16));  // 分
                i++;
                resEntity.setSecond(Integer.parseInt(dataList.get(i), 16));  // 秒
                if(StrUtil.equals(DEVICE_ID,deviceId)){
                    i++;//编号
                    resEntity.setNum1(Integer.parseInt(dataList.get(i),16));
                    //温度1
                    i++;
                    resEntity.setTemp1(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+dataList.get(i + 1)));
                    i++;
                    i++;
                    //编号2
                    resEntity.setNum2(Integer.parseInt(dataList.get(i),16));
                    //温度2
                    i++;
                    resEntity.setTemp2(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+dataList.get(i + 1)));
                } else {
                    i++; // 温度1   四位一组
                    resEntity.setTemp1(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+dataList.get(i + 1)));
                    i +=2;
                    resEntity.setMin1(Integer.parseInt(dataList.get(i), 16));  // 分2
                    i ++;
                    resEntity.setSecond1(Integer.parseInt(dataList.get(i), 16));  // 秒2
                    i++; // 温度2
                    resEntity.setTemp2(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+ dataList.get(i + 1)));
                }


                asphaltSofteningPointResService.saveOrUpdate(resEntity);
            } else {
                throw new RenException("沥青软化点数据解析异常：" + resData);
            }
        } catch (Exception e) {
            errorRecordService.saveErrorData(ZhjdIotUtils.ASPHALT_SOFTENING_POINT, deviceId, resData);
            throw new RenException("数据解析异常");
        }
    }

    /**
     * 解析沥青软化点试验仪数据
     *
     * @param resData  试验结果数据
     * @param deviceId 试验设备id
     */
//    @Override
//    public void parsingData(String resData, String deviceId) {
//        Date nowDate = new Date();
//        try {
//            List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(resData);
//            //如果数据以00开头，可能设备刚开机或重启，表示一次新的实验开始
//            if (StringUtils.equals(dataList.get(0), "00")) {
//                currentMap.remove(deviceId);
//            }
//            //验证位不进行校验
//            int i = 4;
//            //试验数据
//            if (StringUtils.equals(ZhjdIotUtils.DATA_TYPE_TEST, dataList.get(i))) {
//                AsphaltSofteningPointEntity entity = new AsphaltSofteningPointEntity();
//                entity.setDeviceId(deviceId);
//                if (currentMap.get(deviceId) == null) {
//                    AsphaltSofteningPointResEntity resEntity = new AsphaltSofteningPointResEntity();
//                    resEntity.setDeviceId(deviceId);
//                    asphaltSofteningPointResService.save(resEntity);
//                    currentMap.put(deviceId, resEntity.getId());
//                }
//                //设置实验结果数据id
//                entity.setResId(currentMap.get(deviceId));
//
//                entity.setOriginalData(resData);
//                entity.setCreateTime(nowDate);
//                i++;
//                entity.setFlag(dataList.get(i));
//
//                // 将16进制转换为10进制数据，不含（0x）
//                i++;
//                entity.setMin(Integer.parseInt(dataList.get(i), 16));  // 分
//                i++;
//                entity.setSecond(Integer.parseInt(dataList.get(i), 16));  // 秒
//                i++;
//                entity.setNum1(Integer.parseInt(dataList.get(i), 16));  // 试件编号1
//                i++; // 温度1
//                entity.setTemp1(ZhjdIotUtils.hexToDecimalism(dataList.get(i), dataList.get(i + 1)));
//                i += 2;
//                entity.setNum2(Integer.parseInt(dataList.get(i), 16));  // 试件编号2
//                i++; // 温度2
//                entity.setTemp2(ZhjdIotUtils.hexToDecimalism(dataList.get(i), dataList.get(i + 1)));
//
//                save(entity);
//                //结果数据
//            } else if (StringUtils.equals(ZhjdIotUtils.DATA_TYPE_RES, dataList.get(i))) {
//                AsphaltSofteningPointResEntity resEntity = new AsphaltSofteningPointResEntity();
//                resEntity.setId(currentMap.get(deviceId));
//                currentMap.remove(deviceId);
//                resEntity.setDeviceId(deviceId);
//                resEntity.setOriginalData(resData);
//                resEntity.setCreateTime(nowDate);
//
//                // 将16进制转换为10进制数据，不含（0x）
//                i++;
//                resEntity.setMin(Integer.parseInt(dataList.get(i), 16));  // 分
//                i++;
//                resEntity.setSecond(Integer.parseInt(dataList.get(i), 16));  // 秒
//                i++;
//                resEntity.setNum1(Integer.parseInt(dataList.get(i), 16));  // 试件编号1
//                i++; // 温度1
//                resEntity.setTemp1(ZhjdIotUtils.hexToDecimalism(dataList.get(i), dataList.get(i + 1)));
//                i += 2;
//                resEntity.setNum2(Integer.parseInt(dataList.get(i), 16));  // 试件编号2
//                i++; // 温度2
//                resEntity.setTemp2(ZhjdIotUtils.hexToDecimalism(dataList.get(i), dataList.get(i + 1)));
//
//                asphaltSofteningPointResService.saveOrUpdate(resEntity);
//            } else {
//                throw new RenException("沥青软化点数据解析异常：" + resData);
//            }
//        } catch (Exception e) {
//            errorRecordService.saveErrorData(ZhjdIotUtils.ASPHALT_SOFTENING_POINT, deviceId, resData);
//            throw new RenException("数据解析异常");
//        }
//    }

//    public static void main(String[] args) {
//        parsingData1("FAFBFC09A400000000F705009A", "23");
//    }

    /**
     * 绑定材料
     * @param asphaltSofteningPointRes
     */
    public void changeSample(AsphaltSofteningPointResEntity asphaltSofteningPointRes) {
        //更新试验结果表
        asphaltSofteningPointResService.updateById(asphaltSofteningPointRes);
        //查询试验过程数据
        List<AsphaltSofteningPointEntity> processList = list(new LambdaQueryWrapper<AsphaltSofteningPointEntity>().eq(AsphaltSofteningPointEntity::getResId, asphaltSofteningPointRes.getId()));
        if (CollectionUtil.isNotEmpty(processList)) {
            for (AsphaltSofteningPointEntity item : processList) {
                item.setSampleId(asphaltSofteningPointRes.getSampleId());
            }
            updateBatchById(processList);
        }
    }

    /**
     * 二标解析沥青软化点数据
     *
     * 返回 01 03 1E 00 02 00 00 00 06 06 9C 01 F4 00 05 00 7A 00 00 05 57 08 E5 05 8A 06 97 00 01 00 02 00 32 3E 2E
     * 01       从机地址
     * 03       读指令
     * 1E       数据内容字节数（30个字节）
     * 00 02    设备代号2
     * 00 00    当前温度
     * 00 06    溶液介质
     * 06 9C   当前试验编号
     * 01 F4   试验运行分
     * 00 05   试验运行秒
     * 00 7A   软化点1
     * 00 00   软化点2
     * 05 57   平均软化点；
     * 08 E5   试验完成标志（0试验未完成 1试验完成）
     * 05 8A   试验状态
     * 06 97   试验失败标志
     * 00 01   激光1路线状态
     * 00 02   激光1路线状态
     * 00 32   。。。
     * 3E 2E   。。。
     *  小数点一位，当实验完成标志=1时，代表结果数据，=0为过程数据；
     * @param resData 试验结果数据
     * @param deviceId 试验设备id
     */
    @Override
    public void parsingDataTwob(String resData, String deviceId) {
        Date nowDate = new Date();
        try {
            List<String> dataList = ZhjdIotUtils.stringToList(resData);
            AsphaltSofteningPointEntity entity = new AsphaltSofteningPointEntity();
            AsphaltSofteningPointResEntity resEntity = new AsphaltSofteningPointResEntity();
            resEntity.setCreateTime(nowDate);
            if(currentMap.get(deviceId) == null){
                resEntity.setDeviceId(deviceId);
                asphaltSofteningPointResService.save(resEntity);
                currentMap.put(deviceId,resEntity.getId());
            }
            //验证位不进行校验
            int i = 3;
            //设备代号；
//            resEntity.setDeviceCode(getValue(dataList,i));
            i+=2;
            resEntity.setCurTemp(ZhjdIotUtils.hexToOnePoint(dataList.get(i) + dataList.get(i + 1)));
            i+=2;//溶液介质
            i+=2;//当前试验编号
            resEntity.setTestNo(getValue(dataList,i));
            i+=2;//试验运行分；
            resEntity.setMin(Integer.parseInt(dataList.get(i)+dataList.get(i + 1), 16));
            i+=2;//试验运行秒；
            resEntity.setSecond(Integer.parseInt(dataList.get(i)+dataList.get(i + 1), 16));
            i+=2;//软化点1；
            resEntity.setTemp1(ZhjdIotUtils.hexToTwoPoint(dataList.get(i) + dataList.get(i + 1)));
            i+=2;//软化点2；
            resEntity.setTemp2(ZhjdIotUtils.hexToTwoPoint(dataList.get(i) + dataList.get(i + 1)));
            i+=2;//平均软化点；
            resEntity.setAvgTemp(ZhjdIotUtils.hexToTwoPoint(dataList.get(i) + dataList.get(i + 1)));
            asphaltSofteningPointResService.saveOrUpdate(resEntity);

        } catch (Exception e) {
            errorRecordService.saveErrorData(ZhjdIotUtils.ASPHALT_PENETROMETER, deviceId, resData);
            throw new RenException("数据解析异常");
        }
    }

    /**
     * 重新解析航天科宇设备沥青软化点数据；
     * 1、解析结果数据；
     * 2、解析过程数据；
     * @param deviceId
     */
    @Override
    public void reParsingData(String deviceId) {
//        if(StringUtils.isBlank(deviceId)){
//            return;
//        }
//        1.解析结果数据；
        List<AsphaltSofteningPointResEntity> resEntities = resMapper.selectList(new LambdaQueryWrapper<AsphaltSofteningPointResEntity>()
                .eq(StringUtils.isNotBlank(deviceId),AsphaltSofteningPointResEntity::getDeviceId,deviceId)
                .isNotNull(AsphaltSofteningPointResEntity::getOriginalData));
        if(CollUtil.isEmpty(resEntities)){
            return;
        }

        for(AsphaltSofteningPointResEntity resEntity : resEntities) {
            String originalData = resEntity.getOriginalData();
            List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(originalData);
            int i = 5;
            resEntity.setMin(Integer.parseInt(dataList.get(i), 16));  // 分
            i++;
            resEntity.setSecond(Integer.parseInt(dataList.get(i), 16));  // 秒
            i++; // 温度1   四位一组
            resEntity.setTemp1(ZhjdIotUtils.hexToOnePoint(dataList.get(i) + dataList.get(i + 1)));
            i+=2;
            resEntity.setMin1(Integer.parseInt(dataList.get(i), 16));  // 分2
            i++;
            resEntity.setSecond1(Integer.parseInt(dataList.get(i), 16));  // 秒2
            i++; // 温度2
            resEntity.setTemp2(ZhjdIotUtils.hexToOnePoint(dataList.get(i) + dataList.get(i + 1)));
            resMapper.updateById(resEntity);

        }
//        解析过程数据；
        //2.解析过程数据；
        Set<String> resIds = resEntities.stream().map(AsphaltSofteningPointResEntity::getId).collect(Collectors.toSet());
        List<AsphaltSofteningPointEntity> entities = baseMapper.selectList(new LambdaQueryWrapper<AsphaltSofteningPointEntity>()
                .in(AsphaltSofteningPointEntity::getResId,resIds)
                .eq(AsphaltSofteningPointEntity::getFlag,"01")
                .isNotNull(AsphaltSofteningPointEntity::getOriginalData));
        if(CollUtil.isEmpty(entities)){
            return;
        }
        for(AsphaltSofteningPointEntity entity: entities){
            String originalData = entity.getOriginalData();
            List<String> dataList = ZhjdIotUtils.analyzeExperimentalData(originalData);
            int i = 5;
            entity.setFlag(dataList.get(i));
            i++;
            entity.setMin(Integer.parseInt(dataList.get(i), 16));  // 分
            i++;
            entity.setSecond(Integer.parseInt(dataList.get(i), 16));  // 秒
            i++; // 温度1
            entity.setTemp1(ZhjdIotUtils.hexToOnePoint(dataList.get(i)+dataList.get(i + 1)));
            i ++;
            entity.setStirringGear(dataList.get(i));
            i++;
            entity.setStatus(dataList.get(i));
            baseMapper.updateById(entity);
        }
    }

    private String getValue(List<String> dataList,int i) {
        return String.valueOf(Integer.parseInt(dataList.get(i)+dataList.get(i + 1), 16));
    }
}
